/* main.c - Application main entry point */

/*
 * Copyright (c) 2016 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(net_test, CONFIG_NET_UTILS_LOG_LEVEL);

#include <zephyr/kernel.h>
#include <zephyr/ztest_assert.h>
#include <zephyr/types.h>
#include <stddef.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <zephyr/device.h>
#include <zephyr/init.h>
#include <zephyr/sys/printk.h>
#include <zephyr/net/net_core.h>
#include <zephyr/net/net_ip.h>
#include <zephyr/net/ethernet.h>
#include <zephyr/linker/sections.h>

#include <zephyr/tc_util.h>
#include <zephyr/ztest.h>

#define NET_LOG_ENABLED 1
#include "net_private.h"

struct net_addr_test_data {
	sa_family_t family;
	bool pton;

	struct {
		char c_addr[16];
		char c_verify[16];
		struct in_addr addr;
		struct in_addr verify;
	} ipv4;

	struct {
		char c_addr[46];
		char c_verify[46];
		struct in6_addr addr;
		struct in6_addr verify;
	} ipv6;
};

static ZTEST_DMEM struct net_addr_test_data ipv4_pton_1 = {
	.family = AF_INET,
	.pton = true,
	.ipv4.c_addr = "192.0.0.1",
	.ipv4.verify.s4_addr = { 192, 0, 0, 1 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_pton_2 = {
	.family = AF_INET,
	.pton = true,
	.ipv4.c_addr = "192.1.0.0",
	.ipv4.verify.s4_addr = { 192, 1, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_pton_3 = {
	.family = AF_INET,
	.pton = true,
	.ipv4.c_addr = "192.0.0.0",
	.ipv4.verify.s4_addr = { 192, 0, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_pton_4 = {
	.family = AF_INET,
	.pton = true,
	.ipv4.c_addr = "255.255.255.255",
	.ipv4.verify.s4_addr = { 255, 255, 255, 255 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_pton_5 = {
	.family = AF_INET,
	.pton = true,
	.ipv4.c_addr = "0.0.0.0",
	.ipv4.verify.s4_addr = { 0, 0, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_pton_6 = {
	.family = AF_INET,
	.pton = true,
	.ipv4.c_addr = "0.0.0.1",
	.ipv4.verify.s4_addr = { 0, 0, 0, 1 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_pton_7 = {
	.family = AF_INET,
	.pton = true,
	.ipv4.c_addr = "0.0.1.0",
	.ipv4.verify.s4_addr = { 0, 0, 1, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_pton_8 = {
	.family = AF_INET,
	.pton = true,
	.ipv4.c_addr = "0.1.0.0",
	.ipv4.verify.s4_addr = { 0, 1, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_pton_1 = {
	.family = AF_INET6,
	.pton = true,
	.ipv6.c_addr = "ff08::",
	.ipv6.verify.s6_addr16 = { htons(0xff08), 0, 0, 0, 0, 0, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_pton_2 = {
	.family = AF_INET6,
	.pton = true,
	.ipv6.c_addr = "::",
	.ipv6.verify.s6_addr16 = { 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_pton_3 = {
	.family = AF_INET6,
	.pton = true,
	.ipv6.c_addr = "ff08::1",
	.ipv6.verify.s6_addr16 = { htons(0xff08), 0, 0, 0, 0, 0, 0, htons(1) },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_pton_4 = {
	.family = AF_INET6,
	.pton = true,
	.ipv6.c_addr = "2001:db8::1",
	.ipv6.verify.s6_addr16 = { htons(0x2001), htons(0xdb8),
				   0, 0, 0, 0, 0, htons(1) },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_pton_5 = {
	.family = AF_INET6,
	.pton = true,
	.ipv6.c_addr = "2001:db8::2:1",
	.ipv6.verify.s6_addr16 = { htons(0x2001), htons(0xdb8),
				   0, 0, 0, 0, htons(2), htons(1) },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_pton_6 = {
	.family = AF_INET6,
	.pton = true,
	.ipv6.c_addr = "ff08:1122:3344:5566:7788:9900:aabb:ccdd",
	.ipv6.verify.s6_addr16 = { htons(0xff08), htons(0x1122),
				   htons(0x3344), htons(0x5566),
				   htons(0x7788), htons(0x9900),
				   htons(0xaabb), htons(0xccdd) },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_pton_7 = {
	.family = AF_INET6,
	.pton = true,
	.ipv6.c_addr = "0:ff08::",
	.ipv6.verify.s6_addr16 = { 0, htons(0xff08), 0, 0, 0, 0, 0, 0 },
};

/* net_addr_ntop test cases */
static ZTEST_DMEM struct net_addr_test_data ipv4_ntop_1 = {
	.family = AF_INET,
	.pton = false,
	.ipv4.c_verify = "192.0.0.1",
	.ipv4.addr.s4_addr = { 192, 0, 0, 1 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_ntop_2 = {
	.family = AF_INET,
	.pton = false,
	.ipv4.c_verify = "192.1.0.0",
	.ipv4.addr.s4_addr = { 192, 1, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_ntop_3 = {
	.family = AF_INET,
	.pton = false,
	.ipv4.c_verify = "192.0.0.0",
	.ipv4.addr.s4_addr = { 192, 0, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_ntop_4 = {
	.family = AF_INET,
	.pton = false,
	.ipv4.c_verify = "255.255.255.255",
	.ipv4.addr.s4_addr = { 255, 255, 255, 255 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_ntop_5 = {
	.family = AF_INET,
	.pton = false,
	.ipv4.c_verify = "0.0.0.0",
	.ipv4.addr.s4_addr = { 0, 0, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_ntop_6 = {
	.family = AF_INET,
	.pton = false,
	.ipv4.c_verify = "0.0.0.1",
	.ipv4.addr.s4_addr = { 0, 0, 0, 1 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_ntop_7 = {
	.family = AF_INET,
	.pton = false,
	.ipv4.c_verify = "0.0.1.0",
	.ipv4.addr.s4_addr = { 0, 0, 1, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv4_ntop_8 = {
	.family = AF_INET,
	.pton = false,
	.ipv4.c_verify = "0.1.0.0",
	.ipv4.addr.s4_addr = { 0, 1, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_ntop_1 = {
	.family = AF_INET6,
	.pton = false,
	.ipv6.c_verify = "ff08::",
	.ipv6.addr.s6_addr16 = { htons(0xff08), 0, 0, 0, 0, 0, 0, 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_ntop_2 = {
	.family = AF_INET6,
	.pton = false,
	.ipv6.c_verify = "::",
	.ipv6.addr.s6_addr16 = { 0 },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_ntop_3 = {
	.family = AF_INET6,
	.pton = false,
	.ipv6.c_verify = "ff08::1",
	.ipv6.addr.s6_addr16 = { htons(0xff08), 0, 0, 0, 0, 0, 0, htons(1) },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_ntop_4 = {
	.family = AF_INET6,
	.pton = false,
	.ipv6.c_verify = "2001:db8::1",
	.ipv6.addr.s6_addr16 = { htons(0x2001), htons(0xdb8),
				 0, 0, 0, 0, 0, htons(1) },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_ntop_5 = {
	.family = AF_INET6,
	.pton = false,
	.ipv6.c_verify = "2001:db8::2:1",
	.ipv6.addr.s6_addr16 = { htons(0x2001), htons(0xdb8),
				 0, 0, 0, 0, htons(2), htons(1) },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_ntop_6 = {
	.family = AF_INET6,
	.pton = false,
	.ipv6.c_verify = "ff08:1122:3344:5566:7788:9900:aabb:ccdd",
	.ipv6.addr.s6_addr16 = { htons(0xff08), htons(0x1122),
				 htons(0x3344), htons(0x5566),
				 htons(0x7788), htons(0x9900),
				 htons(0xaabb), htons(0xccdd) },
};

static ZTEST_DMEM struct net_addr_test_data ipv6_ntop_7 = {
	.family = AF_INET6,
	.pton = false,
	.ipv6.c_verify = "0:ff08::",
	.ipv6.addr.s6_addr16 = { 0, htons(0xff08), 0, 0, 0, 0, 0, 0 },
};

static const struct {
	const char *name;
	struct net_addr_test_data *data;
} tests[] = {
	/* IPv4 net_addr_pton */
	{ "test_ipv4_pton_1", &ipv4_pton_1},
	{ "test_ipv4_pton_2", &ipv4_pton_2},
	{ "test_ipv4_pton_3", &ipv4_pton_3},
	{ "test_ipv4_pton_4", &ipv4_pton_4},
	{ "test_ipv4_pton_5", &ipv4_pton_5},
	{ "test_ipv4_pton_6", &ipv4_pton_6},
	{ "test_ipv4_pton_7", &ipv4_pton_7},
	{ "test_ipv4_pton_8", &ipv4_pton_8},

	/* IPv6 net_addr_pton */
	{ "test_ipv6_pton_1", &ipv6_pton_1},
	{ "test_ipv6_pton_2", &ipv6_pton_2},
	{ "test_ipv6_pton_3", &ipv6_pton_3},
	{ "test_ipv6_pton_4", &ipv6_pton_4},
	{ "test_ipv6_pton_5", &ipv6_pton_5},
	{ "test_ipv6_pton_6", &ipv6_pton_6},
	{ "test_ipv6_pton_7", &ipv6_pton_7},

	/* IPv4 net_addr_ntop */
	{ "test_ipv4_ntop_1", &ipv4_ntop_1},
	{ "test_ipv4_ntop_2", &ipv4_ntop_2},
	{ "test_ipv4_ntop_3", &ipv4_ntop_3},
	{ "test_ipv4_ntop_4", &ipv4_ntop_4},
	{ "test_ipv4_ntop_5", &ipv4_ntop_5},
	{ "test_ipv4_ntop_6", &ipv4_ntop_6},
	{ "test_ipv4_ntop_7", &ipv4_ntop_7},
	{ "test_ipv4_ntop_8", &ipv4_ntop_8},

	/* IPv6 net_addr_ntop */
	{ "test_ipv6_ntop_1", &ipv6_ntop_1},
	{ "test_ipv6_ntop_2", &ipv6_ntop_2},
	{ "test_ipv6_ntop_3", &ipv6_ntop_3},
	{ "test_ipv6_ntop_4", &ipv6_ntop_4},
	{ "test_ipv6_ntop_5", &ipv6_ntop_5},
	{ "test_ipv6_ntop_6", &ipv6_ntop_6},
	{ "test_ipv6_ntop_7", &ipv6_ntop_7},
};

static bool check_net_addr(struct net_addr_test_data *data)
{
	switch (data->family) {
	case AF_INET:
		if (data->pton) {
			if (net_addr_pton(AF_INET, (char *)data->ipv4.c_addr,
					  &data->ipv4.addr) < 0) {
				printk("Failed to convert %s\n",
				       data->ipv4.c_addr);

				return false;
			}

			if (!net_ipv4_addr_cmp(&data->ipv4.addr,
					       &data->ipv4.verify)) {
				printk("Failed to verify %s\n",
				       data->ipv4.c_addr);

				return false;
			}
		} else {
			if (!net_addr_ntop(AF_INET, &data->ipv4.addr,
					   data->ipv4.c_addr,
					   sizeof(data->ipv4.c_addr))) {
				printk("Failed to convert %s\n",
				       net_sprint_ipv4_addr(&data->ipv4.addr));

				return false;
			}

			if (strcmp(data->ipv4.c_addr, data->ipv4.c_verify)) {
				printk("Failed to verify %s\n",
				       data->ipv4.c_addr);
				printk("against %s\n",
				       data->ipv4.c_verify);

				return false;
			}
		}

		break;

	case AF_INET6:
		if (data->pton) {
			if (net_addr_pton(AF_INET6, (char *)data->ipv6.c_addr,
					  &data->ipv6.addr) < 0) {
				printk("Failed to convert %s\n",
				       data->ipv6.c_addr);

				return false;
			}

			if (!net_ipv6_addr_cmp(&data->ipv6.addr,
					       &data->ipv6.verify)) {
				printk("Failed to verify %s\n",
				       net_sprint_ipv6_addr(&data->ipv6.addr));
				printk("against %s\n",
				       net_sprint_ipv6_addr(
							&data->ipv6.verify));

				return false;
			}
		} else {
			if (!net_addr_ntop(AF_INET6, &data->ipv6.addr,
					   data->ipv6.c_addr,
					   sizeof(data->ipv6.c_addr))) {
				printk("Failed to convert %s\n",
				       net_sprint_ipv6_addr(&data->ipv6.addr));

				return false;
			}

			if (strcmp(data->ipv6.c_addr, data->ipv6.c_verify)) {
				printk("Failed to verify %s\n",
				       data->ipv6.c_addr);
				printk("against %s\n",
				       data->ipv6.c_verify);

				return false;
			}

		}

		break;
	}

	return true;
}

ZTEST(test_utils_fn, test_net_addr)
{
	int count, pass;

	for (count = 0, pass = 0; count < ARRAY_SIZE(tests); count++) {
		TC_PRINT("Running test: %s: ", tests[count].name);

		if (check_net_addr(tests[count].data)) {
			TC_PRINT("passed\n");
			pass++;
		} else {
			TC_PRINT("failed\n");
		}
	}

	zassert_equal(pass, ARRAY_SIZE(tests), "check_net_addr error");
}

ZTEST(test_utils_fn, test_addr_parse)
{
	struct sockaddr addr;
	bool ret;
	int i;
#if defined(CONFIG_NET_IPV4)
	static const struct {
		const char *address;
		int len;
		struct sockaddr_in result;
		bool verdict;
	} parse_ipv4_entries[] = {
		{
			.address = "192.0.2.1:80",
			.len = sizeof("192.0.2.1:80") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_port = htons(80),
				.sin_addr = {
					.s4_addr[0] = 192,
					.s4_addr[1] = 0,
					.s4_addr[2] = 2,
					.s4_addr[3] = 1
				}
			},
			.verdict = true
		},
		{
			.address = "192.0.2.2",
			.len = sizeof("192.0.2.2") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_port = 0,
				.sin_addr = {
					.s4_addr[0] = 192,
					.s4_addr[1] = 0,
					.s4_addr[2] = 2,
					.s4_addr[3] = 2
				}
			},
			.verdict = true
		},
		{
			.address = "192.0.2.3/foobar",
			.len = sizeof("192.0.2.3/foobar") - 8,
			.result = {
				.sin_family = AF_INET,
				.sin_port = 0,
				.sin_addr = {
					.s4_addr[0] = 192,
					.s4_addr[1] = 0,
					.s4_addr[2] = 2,
					.s4_addr[3] = 3
				}
			},
			.verdict = true
		},
		{
			.address = "255.255.255.255:0",
			.len = sizeof("255.255.255.255:0") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_port = 0,
				.sin_addr = {
					.s4_addr[0] = 255,
					.s4_addr[1] = 255,
					.s4_addr[2] = 255,
					.s4_addr[3] = 255
				}
			},
			.verdict = true
		},
		{
			.address = "127.0.0.42:65535",
			.len = sizeof("127.0.0.42:65535") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_port = htons(65535),
				.sin_addr = {
					.s4_addr[0] = 127,
					.s4_addr[1] = 0,
					.s4_addr[2] = 0,
					.s4_addr[3] = 42
				}
			},
			.verdict = true
		},
		{
			.address = "192.0.2.3:80/foobar",
			.len = sizeof("192.0.2.3:80/foobar") - 1,
			.verdict = false
		},
		{
			.address = "192.168.1.1:65536/foobar",
			.len = sizeof("192.168.1.1:65536") - 1,
			.verdict = false
		},
		{
			.address = "192.0.2.3:80/foobar",
			.len = sizeof("192.0.2.3") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_port = 0,
				.sin_addr = {
					.s4_addr[0] = 192,
					.s4_addr[1] = 0,
					.s4_addr[2] = 2,
					.s4_addr[3] = 3
				}
			},
			.verdict = true
		},
		{
			.address = "192.0.2.3:80/foobar",
			.len = sizeof("192.0.2.3:80") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_port = htons(80),
				.sin_addr = {
					.s4_addr[0] = 192,
					.s4_addr[1] = 0,
					.s4_addr[2] = 2,
					.s4_addr[3] = 3
				}
			},
			.verdict = true
		},
		{
			.address = "192.0.2.3/foobar",
			.len = sizeof("192.0.2.3/foobar") - 1,
			.verdict = false
		},
		{
			.address = "192.0.2.3:80:80",
			.len = sizeof("192.0.2.3:80:80") - 1,
			.verdict = false
		},
		{
			.address = "192.0.2.1:80000",
			.len = sizeof("192.0.2.1:80000") - 1,
			.verdict = false
		},
		{
			.address = "192.168.0.1",
			.len = sizeof("192.168.0.1:80000") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_port = 0,
				.sin_addr = {
					.s4_addr[0] = 192,
					.s4_addr[1] = 168,
					.s4_addr[2] = 0,
					.s4_addr[3] = 1
				}
			},
			.verdict = true
		},
		{
			.address = "a.b.c.d",
			.verdict = false
		},
	};
#endif
#if defined(CONFIG_NET_IPV6)
	static const struct {
		const char *address;
		int len;
		struct sockaddr_in6 result;
		bool verdict;
	} parse_ipv6_entries[] = {
		{
			.address = "[2001:db8::2]:80",
			.len = sizeof("[2001:db8::2]:80") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = htons(80),
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(2)
				}
			},
			.verdict = true
		},
		{
			.address = "[2001:db8::a]/barfoo",
			.len = sizeof("[2001:db8::a]/barfoo") - 8,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(0xa)
				}
			},
			.verdict = true
		},
		{
			.address = "[2001:db8::a]",
			.len = sizeof("[2001:db8::a]") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(0xa)
				}
			},
			.verdict = true
		},
		{
			.address = "[2001:db8:3:4:5:6:7:8]:65535",
			.len = sizeof("[2001:db8:3:4:5:6:7:8]:65535") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 65535,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[2] = ntohs(3),
					.s6_addr16[3] = ntohs(4),
					.s6_addr16[4] = ntohs(5),
					.s6_addr16[5] = ntohs(6),
					.s6_addr16[6] = ntohs(7),
					.s6_addr16[7] = ntohs(8),
				}
			},
			.verdict = true
		},
		{
			.address = "[::]:0",
			.len = sizeof("[::]:0") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = 0,
					.s6_addr16[1] = 0,
					.s6_addr16[2] = 0,
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = 0,
				}
			},
			.verdict = true
		},
		{
			.address = "2001:db8::42",
			.len = sizeof("2001:db8::42") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(0x42)
				}
			},
			.verdict = true
		},
		{
			.address = "[2001:db8::192.0.2.1]:80000",
			.len = sizeof("[2001:db8::192.0.2.1]:80000") - 1,
			.verdict = false
		},
		{
			.address = "[2001:db8::1]:80",
			.len = sizeof("[2001:db8::1") - 1,
			.verdict = false
		},
		{
			.address = "[2001:db8::1]:65536",
			.len = sizeof("[2001:db8::1]:65536") - 1,
			.verdict = false
		},
		{
			.address = "[2001:db8::1]:80",
			.len = sizeof("2001:db8::1") - 1,
			.verdict = false
		},
		{
			.address = "[2001:db8::1]:a",
			.len = sizeof("[2001:db8::1]:a") - 1,
			.verdict = false
		},
		{
			.address = "[2001:db8::1]:10-12",
			.len = sizeof("[2001:db8::1]:10-12") - 1,
			.verdict = false
		},
		{
			.address = "[2001:db8::]:80/url/continues",
			.len = sizeof("[2001:db8::]") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = 0,
				}
			},
			.verdict = true
		},
		{
			.address = "[2001:db8::200]:080",
			.len = sizeof("[2001:db8:433:2]:80000") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = htons(80),
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(0x200)
				}
			},
			.verdict = true
		},
		{
			.address = "[2001:db8::]:8080/another/url",
			.len = sizeof("[2001:db8::]:8080/another/url") - 1,
			.verdict = false
		},
		{
			.address = "[2001:db8::1",
			.len = sizeof("[2001:db8::1") - 1,
			.verdict = false
		},
		{
			.address = "[2001:db8::1]:-1",
			.len = sizeof("[2001:db8::1]:-1") - 1,
			.verdict = false
		},
		{
			/* Valid although user probably did not mean this */
			.address = "2001:db8::1:80",
			.len = sizeof("2001:db8::1:80") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = ntohs(0x01),
					.s6_addr16[7] = ntohs(0x80)
				}
			},
			.verdict = true
		},
	};
#endif

#if defined(CONFIG_NET_IPV4)
	for (i = 0; i < ARRAY_SIZE(parse_ipv4_entries) - 1; i++) {
		(void)memset(&addr, 0, sizeof(addr));

		ret = net_ipaddr_parse(
			parse_ipv4_entries[i].address,
			parse_ipv4_entries[i].len,
			&addr);
		if (ret != parse_ipv4_entries[i].verdict) {
			printk("IPv4 entry [%d] \"%s\" failed\n", i,
				parse_ipv4_entries[i].address);
			zassert_true(false, "failure");
		}

		if (ret == true) {
			zassert_true(
				net_ipv4_addr_cmp(
				      &net_sin(&addr)->sin_addr,
				      &parse_ipv4_entries[i].result.sin_addr) ==
				parse_ipv4_entries[i].verdict);
			zassert_true(net_sin(&addr)->sin_port ==
				     parse_ipv4_entries[i].result.sin_port,
				     "IPv4 port");
			zassert_true(net_sin(&addr)->sin_family ==
				     parse_ipv4_entries[i].result.sin_family,
				     "IPv4 family");
		}
	}
#endif
#if defined(CONFIG_NET_IPV6)
	for (i = 0; i < ARRAY_SIZE(parse_ipv6_entries) - 1; i++) {
		(void)memset(&addr, 0, sizeof(addr));

		ret = net_ipaddr_parse(
			parse_ipv6_entries[i].address,
			parse_ipv6_entries[i].len,
			&addr);
		if (ret != parse_ipv6_entries[i].verdict) {
			printk("IPv6 entry [%d] \"%s\" failed\n", i,
			       parse_ipv6_entries[i].address);
			zassert_true(false, "failure");
		}

		if (ret == true) {
			zassert_true(
				net_ipv6_addr_cmp(
				      &net_sin6(&addr)->sin6_addr,
				      &parse_ipv6_entries[i].result.sin6_addr) ==
				parse_ipv6_entries[i].verdict);
			zassert_true(net_sin6(&addr)->sin6_port ==
				     parse_ipv6_entries[i].result.sin6_port,
				     "IPv6 port");
			zassert_true(net_sin6(&addr)->sin6_family ==
				     parse_ipv6_entries[i].result.sin6_family,
				     "IPv6 family");
		}
	}
#endif
}

#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
static const char *check_ipaddr(const char *addresses)
{
	do {
		char addr_str[NET_IPV6_ADDR_LEN + 4 + 1];
		char expecting[NET_IPV6_ADDR_LEN + 4 + 1];
		const char *orig = addresses;
		struct sockaddr_storage addr;
		struct sockaddr_storage mask;
		uint8_t mask_len;
		int ret;

		memset(&addr, 0, sizeof(addr));
		mask_len = 0;

		memset(addr_str, 0, sizeof(addr_str));
		memset(expecting, 0, sizeof(expecting));

		addresses = net_ipaddr_parse_mask(addresses, strlen(addresses),
						  (struct sockaddr *)&addr, &mask_len);
		zassert_not_null(addresses, "Invalid parse, expecting \"%s\"", orig);

		strncpy(expecting, orig,
			*addresses == '\0' ? strlen(orig) : addresses - orig - 1);

		(void)net_addr_ntop(addr.ss_family,
				    &net_sin((struct sockaddr *)&addr)->sin_addr,
				    addr_str, sizeof(addr_str));

		ret = net_mask_len_to_netmask(addr.ss_family, mask_len,
					      (struct sockaddr *)&mask);
		zassert_equal(ret, 0, "Failed to convert mask %d", mask_len);

		ret = net_netmask_to_mask_len(addr.ss_family,
					      (struct sockaddr *)&mask,
					      &mask_len);
		zassert_equal(ret, 0, "Failed to convert mask %s",
			      net_sprint_addr(addr.ss_family,
					      (const void *)&net_sin(
						      ((struct sockaddr *)&mask))->sin_addr));

		if (net_sin((struct sockaddr *)&mask)->sin_addr.s_addr != 0) {
			int addr_len = strlen(addr_str);

			snprintk(addr_str + addr_len,
				 sizeof(addr_str) - addr_len,
				 "/%d", mask_len);
		}

		zassert_mem_equal(addr_str, expecting,
				  *addresses == '\0' ? strlen(orig) : addresses - orig - 1,
				  "Address mismatch, expecing %s, got %s (len %d)\n",
				  expecting, addr_str, addresses - orig - 1);
	} while (addresses != NULL && *addresses != '\0');

	return addresses;
}
#endif /* CONFIG_NET_IPV4 && CONFIG_NET_IPV6 */

ZTEST(test_utils_fn, test_addr_parse_mask)
{
	struct sockaddr addr;
	uint8_t mask_len;
	const char *next;
	int i;
#if defined(CONFIG_NET_IPV4)
	static const struct {
		const char *address;
		int len;
		struct sockaddr_in result;
		uint8_t mask_len;
		const char *verdict;
	} parse_ipv4_entries[] = {
		{
			.address = "192.0.2.1:80",
			.len = sizeof("192.0.2.1:80") - 1,
			.verdict = NULL,
		},
		{
			.address = "192.0.2.2",
			.len = sizeof("192.0.2.2") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_addr = {
					.s4_addr[0] = 192,
					.s4_addr[1] = 0,
					.s4_addr[2] = 2,
					.s4_addr[3] = 2
				}
			},
			.verdict = "",
		},
		{
			.address = "192.0.2.3/foobar",
			.len = sizeof("192.0.2.3/foobar") - 1,
			.verdict = NULL,
		},
		{
			.address = "127.0.0.42,1.2.3.4",
			.len = sizeof("127.0.0.42,1.2.3.4") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_addr = {
					.s4_addr[0] = 127,
					.s4_addr[1] = 0,
					.s4_addr[2] = 0,
					.s4_addr[3] = 42
				}
			},
			.mask_len = 32,
			.verdict = &"127.0.0.42,1.2.3.4"[11],
		},
		{
			.address = "127.0.0.42/8,1.2.3.4",
			.len = sizeof("127.0.0.42/8,1.2.3.4") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_addr = {
					.s4_addr[0] = 127,
					.s4_addr[1] = 0,
					.s4_addr[2] = 0,
					.s4_addr[3] = 42
				}
			},
			.mask_len = 8,
			.verdict = &"127.0.0.42/8,1.2.3.4"[13],
		},
		{
			.address = "192.0.2.3:80/foobar",
			.len = sizeof("192.0.2.3:80/foobar") - 1,
			.verdict = false
		},
		{
			.address = "192.168.1.1:65536/foobar",
			.len = sizeof("192.168.1.1:65536") - 1,
			.verdict = false
		},
		{
			.address = "192.0.2.3:80/foobar",
			.len = sizeof("192.0.2.3") - 1,
			.result = {
				.sin_family = AF_INET,
				.sin_port = 0,
				.sin_addr = {
					.s4_addr[0] = 192,
					.s4_addr[1] = 0,
					.s4_addr[2] = 2,
					.s4_addr[3] = 3
				}
			},
			.verdict = "",
		},
		{
			.address = "192.0.2.3:80/foobar",
			.len = sizeof("192.0.2.3:80") - 1,
			.verdict = NULL,
		},
		{
			.address = "a.b.c.d",
			.verdict = false
		},
	};
#endif
#if defined(CONFIG_NET_IPV6)
	static const struct {
		const char *address;
		int len;
		struct sockaddr_in6 result;
		uint8_t mask_len;
		const char *verdict;
	} parse_ipv6_entries[] = {
		{
			.address = "2001:db8::2",
			.len = sizeof("2001:db8::2") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(2)
				}
			},
			.verdict = "",
		},
		{
			.address = "2001:db8::a/barfoo",
			.len = sizeof("2001:db8::a/barfoo") - 8,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(0xa)
				}
			},
			.verdict = "",
		},
		{
			.address = "2001:db8::a",
			.len = sizeof("2001:db8::a") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(0xa)
				}
			},
			.verdict = "",
		},
		{
			.address = "[2001:db8:3:4:5:6:7:8]:65535",
			.len = sizeof("[2001:db8:3:4:5:6:7:8]:65535") - 1,
			.verdict = NULL,
		},
		{
			.address = "[::]:0",
			.len = sizeof("[::]:0") - 1,
			.verdict = NULL,
		},
		{
			.address = "2001:db8::42",
			.len = sizeof("2001:db8::42") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_port = 0,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(0x42)
				}
			},
			.verdict = "",
		},
		{
			.address = "[2001:db8::192.0.2.1]:80000",
			.len = sizeof("[2001:db8::192.0.2.1]:80000") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::1]:80",
			.len = sizeof("[2001:db8::1") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::1]:65536",
			.len = sizeof("[2001:db8::1]:65536") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::1]:80",
			.len = sizeof("2001:db8::1") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::1]:a",
			.len = sizeof("[2001:db8::1]:a") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::1]:10-12",
			.len = sizeof("[2001:db8::1]:10-12") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::]:80/url/continues",
			.len = sizeof("[2001:db8::]") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::200]:080",
			.len = sizeof("[2001:db8:433:2]:80000") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::]:8080/another/url",
			.len = sizeof("[2001:db8::]:8080/another/url") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::1",
			.len = sizeof("[2001:db8::1") - 1,
			.verdict = NULL,
		},
		{
			.address = "[2001:db8::1]:-1",
			.len = sizeof("[2001:db8::1]:-1") - 1,
			.verdict = NULL,
		},
		{
			/* Valid although user probably did not mean this */
			.address = "2001:db8::1:80",
			.len = sizeof("2001:db8::1:80") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = ntohs(0x01),
					.s6_addr16[7] = ntohs(0x80)
				}
			},
			.verdict = "",
		},
		{
			.address = "2001:db8::1/64,2001:db8::2",
			.len = sizeof("2001:db8::1/64,2001:db8::2") - 1,
			.result = {
				.sin6_family = AF_INET6,
				.sin6_addr = {
					.s6_addr16[0] = ntohs(0x2001),
					.s6_addr16[1] = ntohs(0xdb8),
					.s6_addr16[2] = 0,
					.s6_addr16[3] = 0,
					.s6_addr16[4] = 0,
					.s6_addr16[5] = 0,
					.s6_addr16[6] = 0,
					.s6_addr16[7] = ntohs(0x01)
				}
			},
			.mask_len = 64,
			.verdict = &"2001:db8::1/64,2001:db8::2"[14],
		},
	};
#endif

#if defined(CONFIG_NET_IPV4)
	for (i = 0; i < ARRAY_SIZE(parse_ipv4_entries) - 1; i++) {
		(void)memset(&addr, 0, sizeof(addr));
		mask_len = 0;

		next = net_ipaddr_parse_mask(
			parse_ipv4_entries[i].address,
			parse_ipv4_entries[i].len,
			&addr, &mask_len);
		if (next != parse_ipv4_entries[i].verdict) {
			printk("IPv4 entry [%d] \"%s\" failed\n", i,
				parse_ipv4_entries[i].address);
			printk("Points to \"%s\" but should point to \"%s\"\n",
			       next == NULL ? "NULL" : next,
			       parse_ipv4_entries[i].verdict == NULL ?
			       "NULL" : parse_ipv4_entries[i].verdict);
			zassert_true(false, "failure");
		}

		if (next != NULL && *next == '\0') {
			zassert_true(
				net_ipv4_addr_cmp(
				      &net_sin(&addr)->sin_addr,
				      &parse_ipv4_entries[i].result.sin_addr));
			zassert_true(net_sin(&addr)->sin_port == 0,
				     "IPv4 port");
			zassert_true(net_sin(&addr)->sin_family ==
				     parse_ipv4_entries[i].result.sin_family,
				     "IPv4 family");
		}
	}
#endif
#if defined(CONFIG_NET_IPV6)
	for (i = 0; i < ARRAY_SIZE(parse_ipv6_entries) - 1; i++) {
		(void)memset(&addr, 0, sizeof(addr));
		mask_len = 0;

		next = net_ipaddr_parse_mask(
			parse_ipv6_entries[i].address,
			parse_ipv6_entries[i].len,
			&addr, &mask_len);
		if (next != parse_ipv6_entries[i].verdict) {
			printk("IPv6 entry [%d] \"%s\" failed\n", i,
			       parse_ipv6_entries[i].address);
			zassert_true(false, "failure");
		}

		if (next != NULL && *next == '\0') {
			zassert_true(
				net_ipv6_addr_cmp(
				      &net_sin6(&addr)->sin6_addr,
				      &parse_ipv6_entries[i].result.sin6_addr));
			zassert_true(net_sin6(&addr)->sin6_port == 0,
				     "IPv6 port");
			zassert_true(net_sin6(&addr)->sin6_family ==
				     parse_ipv6_entries[i].result.sin6_family,
				     "IPv6 family");
		}
	}
#endif

#if defined(CONFIG_NET_IPV4) && defined(CONFIG_NET_IPV6)
	static const char * const addresses[] = {
		"2001:db8::1/64,192.0.2.1,2001:db8::2,192.0.2.2/24",
		"2001:db8::1/64 192.0.2.1 2001:db8::2 192.0.2.2/24",
		"2001:db8::1/64 192.0.2.1,2001:db8::2 192.0.2.2/24",
		NULL
	};

	i = 0;

	while (addresses[i] != NULL) {
		next = check_ipaddr(addresses[i]);
		zassert_true(next != NULL && *next == '\0',
			     "Invalid parse, expecting \"\", got %p\n", next);
		i++;
	}
#endif /* CONFIG_NET_IPV4 && CONFIG_NET_IPV6 */
}

static uint16_t calc_chksum_ref(uint16_t sum, const uint8_t *data, size_t len)
{
	const uint8_t *end;
	uint16_t tmp;

	end = data + len - 1;

	while (data < end) {
		tmp = (data[0] << 8) + data[1];
		sum += tmp;
		if (sum < tmp) {
			sum++;
		}

		data += 2;
	}

	if (data == end) {
		tmp = data[0] << 8;
		sum += tmp;
		if (sum < tmp) {
			sum++;
		}
	}

	return sum;
}

#define CHECKSUM_TEST_LENGTH 1500

uint8_t testdata[CHECKSUM_TEST_LENGTH];

ZTEST(test_utils_fn, test_ip_checksum)
{
	uint16_t sum_got;
	uint16_t sum_exp;

	/* Simple test dataset */
	for (int i = 0; i < CHECKSUM_TEST_LENGTH; i++) {
		testdata[i] = (uint8_t)i;
	}

	for (int i = 1; i <= CHECKSUM_TEST_LENGTH; i++) {
		sum_got = calc_chksum_ref(i ^ 0x1f13, testdata, i);
		sum_exp = calc_chksum(i ^ 0x1f13, testdata, i);

		zassert_equal(sum_got, sum_exp,
			      "Mismatch between reference and calculated checksum 1\n");
	}

	/* Create a different patten in the data */
	for (int i = 0; i < CHECKSUM_TEST_LENGTH; i++) {
		testdata[i] = (uint8_t)(i + 13) * 17;
	}

	for (int i = 1; i <= CHECKSUM_TEST_LENGTH; i++) {
		sum_got = calc_chksum_ref(i ^ 0x1f13, testdata + (CHECKSUM_TEST_LENGTH - i), i);
		sum_exp = calc_chksum(i ^ 0x1f13, testdata + (CHECKSUM_TEST_LENGTH - i), i);

		zassert_equal(sum_got, sum_exp,
			      "Mismatch between reference and calculated checksum 2\n");
	}

	/* Work across all possible combination so offset and length */
	for (int offset = 0; offset < 7; offset++) {
		for (int length = 1; length < 32; length++) {
			sum_got = calc_chksum_ref(offset ^ 0x8e72, testdata + offset, length);
			sum_exp = calc_chksum(offset ^ 0x8e72, testdata + offset, length);

			zassert_equal(sum_got, sum_exp,
				      "Mismatch between reference and calculated checksum 3\n");
		}
	}
}

/* Verify that the net_pkt pointer to the received link layer address
 * is correct.
 */
ZTEST(test_utils_fn, test_linkaddr_handling)
{
	/* A simple Ethernet frame with IPv4 and UDP headers */
	static const uint8_t udp[] = {
		0x18, 0xfd, 0x74, 0x09, 0xcb, 0x62, 0xac, 0x91,  /* 0000 */
		0xa1, 0x8f, 0x9d, 0xf8, 0x08, 0x00, 0x45, 0x00,  /* 0008 */
		0x00, 0x4c, 0x48, 0x8e, 0x00, 0x00, 0x40, 0x11,  /* 0010 */
		0x57, 0x34, 0xc0, 0xa8, 0x58, 0x29, 0xc1, 0xe5,  /* 0018 */
		0x00, 0x28, 0xba, 0xf0, 0x00, 0x35, 0x00, 0x38,  /* 0020 */
		0xdb, 0x28,
	};

	/* Create net_pkt from the above data, then check the link layer
	 * addresses are properly set even if we pull the data like how
	 * the network stack would do in ethernet.c
	 */
	const uint8_t *dst = &udp[0];
	const uint8_t *src = &udp[NET_ETH_ADDR_LEN];
	uint8_t hdr_len = sizeof(struct net_eth_hdr);
	struct net_linkaddr *lladdr;
	struct net_eth_hdr *hdr;
	struct net_pkt *pkt, *pkt2;
	int ret;

	pkt = net_pkt_rx_alloc_with_buffer(net_if_get_default(),
					   sizeof(udp), AF_UNSPEC,
					   0, K_NO_WAIT);
	zassert_not_null(pkt, "Cannot allocate pkt");

	ret = net_pkt_write(pkt, udp, sizeof(udp));
	zassert_equal(ret, 0, "Cannot write data to pkt");

	hdr = NET_ETH_HDR(pkt);

	/* Set the pointers to ll src and dst addresses */
	lladdr = net_pkt_lladdr_src(pkt);
	memcpy(lladdr->addr, hdr->src.addr, sizeof(struct net_eth_addr));
	lladdr->len = sizeof(struct net_eth_addr);
	lladdr->type = NET_LINK_ETHERNET;

	lladdr = net_pkt_lladdr_dst(pkt);
	memcpy(lladdr->addr, hdr->dst.addr, sizeof(struct net_eth_addr));
	lladdr->len = sizeof(struct net_eth_addr);
	lladdr->type = NET_LINK_ETHERNET;

	zassert_mem_equal(net_pkt_lladdr_src(pkt)->addr,
			  src, NET_ETH_ADDR_LEN,
			  "Source address mismatch");
	zassert_mem_equal(net_pkt_lladdr_dst(pkt)->addr,
			  dst, NET_ETH_ADDR_LEN,
			  "Destination address mismatch");

	pkt2 = net_pkt_clone(pkt, K_NO_WAIT);
	zassert_not_null(pkt2, "Cannot clone pkt");

	/* Make sure we still point to the correct addresses after cloning */
	zassert_mem_equal(net_pkt_lladdr_src(pkt2)->addr,
			  src, NET_ETH_ADDR_LEN,
			  "Source address mismatch");
	zassert_mem_equal(net_pkt_lladdr_dst(pkt2)->addr,
			  dst, NET_ETH_ADDR_LEN,
			  "Destination address mismatch");

	net_pkt_unref(pkt2);

	/* Get rid of the Ethernet header. */
	net_buf_pull(pkt->frags, hdr_len);

	/* Make sure we still point to the correct addresses after pulling
	 * the Ethernet header.
	 */
	zassert_mem_equal(net_pkt_lladdr_src(pkt)->addr,
			  src, NET_ETH_ADDR_LEN,
			  "Source address mismatch");
	zassert_mem_equal(net_pkt_lladdr_dst(pkt)->addr,
			  dst, NET_ETH_ADDR_LEN,
			  "Destination address mismatch");

	/* Clone the packet and check that the link layer addresses are
	 * still correct.
	 */

	pkt2 = net_pkt_clone(pkt, K_NO_WAIT);
	zassert_not_null(pkt2, "Cannot clone pkt");

	zassert_not_equal(net_pkt_lladdr_src(pkt2)->addr,
			  net_pkt_lladdr_src(pkt)->addr,
			  "Source address should not be the same");

	zassert_mem_equal(net_pkt_lladdr_src(pkt2)->addr,
			  src, NET_ETH_ADDR_LEN,
			  "Source address mismatch");
	zassert_mem_equal(net_pkt_lladdr_dst(pkt2)->addr,
			  dst, NET_ETH_ADDR_LEN,
			  "Destination address mismatch");

	net_pkt_unref(pkt);
	net_pkt_unref(pkt2);
}

ZTEST_SUITE(test_utils_fn, NULL, NULL, NULL, NULL, NULL);
